using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.IO;
using Barrage.Global;

namespace Barrage.Language
{
    /// <summary>
    /// A set of Language definitions
    /// </summary>
    public static class Languages{

        /// <summary>
        /// Spanish language definition
        /// </summary>
        public const string Spanish = "ES";
        /// <summary>
        /// English language definition
        /// </summary>
        public const string English = "EN";
        
    }

    /// <summary>
    /// A singleton text cache with a list of texts for a specified languages
    /// </summary>
    public class LanguageManager
    {
        private string currentLanguage = Languages.Spanish;
        private static LanguageManager instance = null;

        /// <summary>
        /// Gets or sets the current loaded language
        /// </summary>
        public static string Language { get { return Texts.currentLanguage; } set { Texts.currentLanguage = value; Texts.reloadAllTexts(); } }

        /// <summary>
        /// Get the class instance
        /// </summary>
        public static LanguageManager Texts { get { if (instance == null) instance = new LanguageManager(); return instance; } }

        private LanguageManager()
        {
            reloadAllTexts();
        }

        private Dictionary<string, string> texts = new Dictionary<string, string>();

        /// <summary>
        /// Get the text associated to the string specified
        /// </summary>
        /// <param name="name">identifier string</param>
        /// <returns>the associated text, or the identifier string itself if the text's not found</returns>
        public string this[string name]
        {
            get
            {
                string text = null;
                if (texts.TryGetValue(name, out text))
                    return text;
                NLog.LogManager.GetLogger("Barrage::LanguageManager").Debug("Text " + name + " not found.");
                return name;
            }
        }

        private void reloadAllTexts()
        {
            texts.Clear();
            DirectoryInfo io = new DirectoryInfo(Store.PathConfig[Store.LANGUAGE_PATH]);
            FileInfo[] fileData = io.GetFiles("*.xml");
            foreach (FileInfo f in fileData)
            {
                AddSource(f.FullName,false);
            }
        }

        private const string XML_LANGUAGE_ROOT = "Language";
        private const string XML_LANG_ATTRIBUTE = "lang";
        private const string XML_TEXT_ELEMENT = "Text";
        private const string XML_ID_ELEMENT = "id";
        private const string XML_VALUE_ELEMENT = "value";

        private void AddSource(string file)
        {
            AddSource(file, true);
        }
        
        private void AddSource(string file,bool defaultPath)
        {
            XmlTextReader reader = null;
            try
            {
                reader = new XmlTextReader((defaultPath?Store.PathConfig[Store.LANGUAGE_PATH]:"") + file);
                reader.WhitespaceHandling = System.Xml.WhitespaceHandling.None;
                while (reader.Read())
                {
                    if (reader.NodeType == XmlNodeType.Element)
                    {
                        if (reader.Name.Equals(XML_LANGUAGE_ROOT))
                        {
                            // If the file language is different to the current language, do nothing
                            if (reader.GetAttribute(XML_LANG_ATTRIBUTE) != currentLanguage)
                                continue;
                            loadLanguageData(reader);
                        }
                    }
                }
                reader.Close();
            }
            catch (Exception e)
            {
                if (reader != null)
                    reader.Close();
                throw new System.Exception("Error parsing language file " + file + ":\n" + e.Message, e);
            }
        }

        private void loadLanguageData(XmlTextReader reader)
        {
            if (!reader.IsEmptyElement)
            {
                int parentDepth = reader.Depth;
                while (reader.Read() && reader.Depth > parentDepth)
                {
                    if ((reader.NodeType == XmlNodeType.Element) && (reader.Name == XML_TEXT_ELEMENT))
                    {
                        string id = reader.GetAttribute(XML_ID_ELEMENT);
                        string value = reader.GetAttribute(XML_VALUE_ELEMENT);
                        if (!texts.ContainsKey(id))
                            texts.Add(id, value);
                    }
                }
            }
        }

    }
}
